package jnpf.fico.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.database.model.entity.DbLinkEntity;
import jnpf.database.plugins.DynamicSourceGeneratorInterface;
import jnpf.database.util.DataSourceUtil;
import jnpf.engine.entity.FlowEngineEntity;
import jnpf.engine.entity.FlowTaskEntity;
import jnpf.engine.enums.FlowStatusEnum;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.service.FlowEngineService;
import jnpf.engine.service.FlowTaskNewService;
import jnpf.engine.service.FlowTaskService;
import jnpf.engine.util.ServiceAllUtil;
import jnpf.exception.WorkFlowException;
import jnpf.fico.entity.*;
import jnpf.fico.mapper.*;
import jnpf.fico.model.bill.ZcBillListVO;
import jnpf.fico.model.operate.ZcBillOperateItemVO;
import jnpf.fico.model.operate.ZcBillOperateVO;
import jnpf.fico.model.operate.ZcglCwBillOperateForm;
import jnpf.fico.service.ZcglCwBillOperateService;
import jnpf.util.DateUtil;
import jnpf.util.JsonUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @description:
 * @author: zhengxiong.jiang
 * @createDate: 2024-10-30
 * @version: 1.0
 */
@Service
@DS("master")
public class ZcglCwBillOperateServiceImpl extends ServiceImpl<ZcglCwBillOperateMapper, ZcglCwBillOperateEntity>
        implements ZcglCwBillOperateService, DynamicSourceGeneratorInterface {


    @Autowired
    private DataSourceUtil dataSourceUtil;
    @Autowired
    private ServiceAllUtil serviceAllUtil;

    @Autowired
    private ZcBillOperateMapper zcBillOperateMapper;
    @Autowired
    private ZcBillOperateItemMapper zcBillOperateItemMapper;
    @Autowired
    private ZcBillMapper zcBillMapper;
    @Autowired
    private ZcBillItemMapper zcBillItemMapper;

    @Autowired
    private UserProvider userProvider;
    @Autowired
    private FlowTaskService flowTaskService;
    @Autowired
    private FlowTaskNewService flowTaskNewService;
    @Autowired
    private FlowEngineService flowEngineService;
    private boolean primaryKeyPolicy = true;


    @Override
    public ZcglCwBillOperateEntity getInfo(String id){
        QueryWrapper<ZcglCwBillOperateEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ZcglCwBillOperateEntity::getId, id);
        return this.getOne(queryWrapper);
    }

    @Override
    @DSTransactional
    public void create(ZcglCwBillOperateEntity entity, String status, String flowId, Map<String, List<String>> candidateList, Map<String,Object> data)throws WorkFlowException {
        String processId = String.valueOf(data.get("flowtaskid"));
        if(primaryKeyPolicy){
            entity.setId(processId);
        }
        this.save(entity);
        if (FlowStatusEnum.submit.getMessage().equals(status)) {
            flow(flowId,processId,data,true,data);
        }else{
            flow(flowId,processId,data,false,data);
        }
    }

    @Override
    @DSTransactional
    public void update(String id, ZcglCwBillOperateEntity entity,String status,String flowId,Map<String, List<String>> candidateList,Map<String,Object> data)throws WorkFlowException{
        entity.setId(id);
        String processId = primaryKeyPolicy ?  id :String.valueOf(data.get("flowtaskid"));
        boolean update = this.updateById(entity);
        if(update){
            if (FlowStatusEnum.submit.getMessage().equals(status)) {
                flow(flowId,processId,data,true,data);
            }else{
                flow(flowId,processId,data,false,data);
            }
        }else{
            throw new WorkFlowException("当前表单原数据已被调整,请重新进入该页面编辑并提交数据");
        }
    }

    @Override
    public ActionResult getOperateInfo(String id) {
        ZcBillOperateEntity zcBillOperateEntity = zcBillOperateMapper.selectById(id);
        if(zcBillOperateEntity==null){
            throw new RuntimeException("账单操作记录为空");
        }
        ZcBillOperateVO zcBillOperateVO = JsonUtil.getJsonToBean(zcBillOperateEntity, ZcBillOperateVO.class);
        List<ZcBillOperateItemEntity> zcBillOperateItemEntities = zcBillOperateItemMapper.selectList(new QueryWrapper<ZcBillOperateItemEntity>()
                .eq("F_ParentId",id)
        );
        List<ZcBillOperateItemVO> jsonToList = JsonUtil.getJsonToList(zcBillOperateItemEntities, ZcBillOperateItemVO.class);
        zcBillOperateVO.setItems(jsonToList);

        ZcBillEntity zcBillEntity=null;

        //获取账单信息
        if(ObjectUtil.isNotNull(zcBillOperateEntity)){
            zcBillEntity = zcBillMapper.selectById(zcBillOperateEntity.getBillId());

            if(ObjectUtil.isNull(zcBillEntity)){
                throw new RuntimeException("账单查询为空");
            }

            ZcBillListVO listVO = JsonUtil.getJsonToBean(zcBillEntity, ZcBillListVO.class);
            //封装计费周期
            Date expenseStartDate = zcBillEntity.getExpenseStartDate();
            Date expenseEndDate = zcBillEntity.getExpenseEndDate();
            if(ObjectUtil.isNotNull(expenseStartDate)&&ObjectUtil.isNotNull(expenseEndDate)){
                listVO.setExpenseCycleDate(DateUtil.dateToString(expenseStartDate, "yyyy-MM-dd")+"至"+DateUtil.dateToString(expenseEndDate, "yyyy-MM-dd"));
            }
            zcBillOperateVO.setZcBillVO(listVO);
        }
        //获取账单详情信息
        if(ObjectUtil.isNotNull(zcBillEntity)){
            List<ZcBillItemEntity> zcBillItemEntities = zcBillItemMapper.selectList(new QueryWrapper<ZcBillItemEntity>()
                    .eq("F_ParentId",zcBillEntity.getId())
            );
            zcBillOperateVO.setBillitems(zcBillItemEntities);
        }


        return ActionResult.success(zcBillOperateVO);
    }


    private void flow(String flowId, String processId, Object formEntity,boolean isSubmit,Map<String,Object> data) throws WorkFlowException {
        DynamicDataSourceContextHolder.poll();
        UserInfo userInfo = userProvider.get();
        FlowEngineEntity flowEngine = flowEngineService.getInfo(flowId);
        FlowTaskEntity flowTaskEntity = flowTaskService.getInfoSubmit(processId, FlowTaskEntity::getId);
        String flowTitle = userInfo.getUserName() + "的" + flowEngine.getFullName();
        String id = flowTaskEntity != null ? flowTaskEntity.getId() : null;
        FlowModel flowModel = JsonUtil.getJsonToBean(data,FlowModel.class);
        flowModel.setId(id);
        flowModel.setFlowId(flowId);
        flowModel.setProcessId(processId);
        flowModel.setFlowTitle(flowTitle);
        flowModel.setFormData(JsonUtil.entityToMap(formEntity));
        flowModel.setUserInfo(userInfo);
        if(isSubmit){
            flowTaskNewService.submit(flowModel);
        }else{
            flowModel.setFlowUrgent(1);
            flowTaskNewService.save(flowModel);
        }
    }

    @Override
    public void data(String id,String data) throws WorkFlowException{
        uniqueAll(JsonUtil.stringToMap(data),1);
        ZcglCwBillOperateForm form =JsonUtil.getJsonToBean(data, ZcglCwBillOperateForm.class );
        ZcglCwBillOperateEntity entity = JsonUtil.getJsonToBean(form, ZcglCwBillOperateEntity.class);
        ZcglCwBillOperateEntity info = getInfo(id);
        entity.setId(info.getId());
        String taskId = StringUtil.isNotEmpty(form.getFlowtaskid())?form.getFlowtaskid():id;
        boolean update = this.updateById(entity);
        if(update){
        }else{
            throw new WorkFlowException("更新失败");
        }
    }

    @Override
    public boolean uniqueAll(Map<String,Object> data,int num)throws WorkFlowException{
        ZcglCwBillOperateForm form =JsonUtil.getJsonToBean(data,ZcglCwBillOperateForm.class );
        Object processId = data.get("flowtaskid");
        int total = 0;
        int result = 0;
        boolean unique = result>0;
        if(unique){
            throw new WorkFlowException("单行输入不能重复");
        }
        return unique;
    }

    @Override
    public void delete(String id){
        ZcglCwBillOperateEntity entity =getInfo(id);
        this.removeById(entity);
    }


    @Override
    public DataSourceUtil getDataSource() {
        DbLinkEntity info = serviceAllUtil.getDbLink(this.getClass().getAnnotation(DS.class).value());
        return info;
    }
}
